#pragma once

#include <functional>

#include <sys/socket.h>
#include <netinet/in.h>

struct Requests
{
};

constexpr std::size_t defaultPollSize = 10;
constexpr int defaultPollTimeout = 1000 * 60 * 3; // ms

struct PollDriver
{
    using Option = std::function<void(PollDriver *)>;

    static auto WithIPV6(bool with = true) -> Option;
    static auto WithIPV4() -> Option;
    static auto WithExceptions(bool with = true) -> Option;
    static auto WithReusable(bool with = true) -> Option;
    static auto WithInitFDSize(std::size_t size = defaultPollSize) -> Option;

    PollDriver(std::initializer_list<Option> opts);
    ~PollDriver();

    Requests Poll() noexcept;

private:
    int check() const;
    void _applyOptions(std::initializer_list<Option> &opts);
    void _createListenFD();
    void _setReusable();
    void _setNonBlocking();
    void _closeListener();
    void _closeClient(std::size_t idx);
    void _bind();
    void _listen();
    void _initPoll();
    void _checkOrThrow(int error);

    struct Options
    {
        bool _with_exceptions = false;
        int _reusable = true;
        int _socket_domain = 0;
        int _poll_timeout = defaultPollTimeout;
        std::size_t _initial_poll_fds_size = defaultPollSize;

        int check() const noexcept
        {
            if (_socket_domain == 0)
            {
                return 1;
            }

            if (_initial_poll_fds_size == 0)
            {
                return 2;
            }
            return 0;
        }
    } _opts;

    int _error = 0;
    int _listen_fd = -1;
    std::vector<struct pollfd> _fds;

    union
    {
        struct sockaddr_in6 in6;
    } _addr;
};
